Go
Impressions
-
Default Access Control controlled by the case of the identifier:
-
Bro .
-
Starting with uppercase letter: Public (exported outside the package).
-
Starting with lowercase letter: Private (accessible only within the same package).
-
-
Does not have null safety.
-
Nothing stood out to me. Not impressive and has few use cases.
-
Meh.
About
About
-
Focus on Concurrency.
-
Uses the keyword
go.
-
-
Go is Golang , same thing.
-
Focus on performance, 'Cloud' and 'Server'.
Memory
-
Has a Garbage Collector.
-
Can store memory addresses, just like C, using & and *.
Safety
-
Default: controlled by the case of the identifier:
-
Starting with uppercase letter: Public (exported outside the package).
-
Starting with lowercase letter: Private (accessible only within the same package).
-
This is widely disliked. I don’t like it and Prime hates it.
-
package main
type MyStruct struct { // Exported (public)
PublicField int
privateField int // Private to the package
}
Syntax
-
Static typing.
-
Has 'var' in function definitions; or you can use ':=' to define the type via value inference.
-
Must pay more attention to declared types.
-
int8, int16, uint16, etc.
-
-
Some low-level caveats exist, despite the syntax being relatively simple.
-
Multiple variables can be defined on a single line, just like Python.
-
Functions can have multiple return values.
something := 2
import 'fmt'
fmt.println('hi')
Goroutines
-
Concurrency vs Parallelism :
-
Goroutines provide concurrency (logical simultaneous execution)
-
Parallel execution requires multiple OS threads
-
-
Default Behavior :
-
By default, Go uses GOMAXPROCS=1, meaning goroutines run on a single OS thread (not parallel)
-
They’re multiplexed onto this thread via cooperative scheduling
-
-
Parallel Execution :
-
When GOMAXPROCS > 1 (set to number of CPU cores by default since Go 1.5)
-
The Go scheduler can distribute goroutines across multiple OS threads
-
These threads can then run in parallel on multiple CPU cores
-
-
Important Notes :
-
Even with GOMAXPROCS>1, parallelism isn’t guaranteed - it depends on:
-
Available CPU cores
-
Workload characteristics
-
Scheduler decisions
-
-
Goroutines are much lighter than OS threads (can have millions)
-
-
To check/change GOMAXPROCS:
fmt.Println(runtime.GOMAXPROCS(0)) // Get current value runtime.GOMAXPROCS(4) // Set to 4 threads
How Goroutines Resemble a Job System (When
GOMAXPROCS > 1
)
-
Similarities :
-
Worker Pool Analogy :
-
Each OS thread (
GOMAXPROCS) acts like a worker in a thread pool -
The Go scheduler assigns goroutines (jobs) to these workers
-
-
Work-Stealing Behavior :
-
If one OS thread (worker) runs out of goroutines, it can "steal" goroutines from another thread's queue
-
Similar to how modern job systems optimize load balancing
-
-
Task Granularity :
-
Goroutines are like small, independent units of work (tasks/jobs)
-
The scheduler manages their distribution across workers
-
-
-
Differences :
-
M:N Scheduling :
-
Go uses M goroutines mapped to N OS threads (where M ≫ N)
-
More efficient than 1:1 thread-per-task systems
-
-
Cooperative Scheduling :
-
Goroutines yield control at specific points (channel ops, syscalls, etc.)
-
Unlike preemptive OS thread scheduling
-
-
Automatic Management :
-
No manual "submit job" API needed - just
go func() -
Scheduler handles balancing automatically
-
-
-
What You Might Lose with Go :
-
Precise Control :
-
Can’t pin goroutines to specific cores
-
Limited influence over scheduler decisions
-
-
GC Pauses :
-
Though usually sub-millisecond, can affect some low-latency apps
-
-
-
-
Goroutines and Channels.
-
-
-
Goroutines are not parallel by default, they are concurrent.
-
package main
import (
"fmt"
"log"
"net/http"
)
func helloHandler(w http.ResponseWriter, r *http.Request) {
// Check HTTP method
if r.Method != http.MethodGet {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
// Get a "name" parameter from URL (ex: /hello?name=John)
name := r.URL.Query().Get("name")
if name == "" {
name = "world"
}
// Respond with a personalized message
message := fmt.Sprintf("Hello, %s!", name)
w.WriteHeader(http.StatusOK)
w.Write([]byte(message))
}
func main() {
// Set up the /hello route
http.HandleFunc("/hello", helloHandler)
// Start the server on port 8080
fmt.Println("Server running at http://localhost:8080")
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatalf("Error starting server: %v", err)
}
}